2011/03/08

Recent entries from same category

  1. Go 言語プログラミングエッセンスという本を書きました。
  2. errors.Join が入った。
  3. unsafe.StringData、unsafe.String、unsafe.SliceData が入った。
  4. Re: Go言語で画像ファイルか確認してみる
  5. net/url に JoinPath が入った。

下記質問にそれぞれ50文字以内を目安に簡単に説明すること。
  1. パッケージ内に定義した関数を外部に公開するにはどうすれば良いか?
  2. 非同期に処理を行う為の命令は?
  3. 関数を抜けた際に処理を実行するにはどうするか?
  4. goroutineの同時実行数を変更するにはどうするか?
  5. コンパイラやリンカが8g/6g/5g、8l/6l/5lという名前になっている理由は?
  6. Goのガベージコレクションの実装は一般的に何と呼ばれている類か?
  7. レシーバがnilの場合にメソッドを呼び出すと何が起きるか?
  8. 可変個引数はどの様に定義するか?
  9. 関数内で定義されるローカル変数のアドレスを戻り値として外部から参照するとどうなるか?
  10. interfaceとstructの違いは何か?
  11. panicを補足して強制終了させない為にはどうするか?




答え


パッケージ内に定義した関数を外部に公開するにはどうすれば良いか?

関数名の先頭を大文字にします。

非同期に処理を行う為の命令は?

go命令を使用します。 package main

import "syscall"

func main() {
    go func() {
        for n := 0; n < 10; n++ {
            println("Hello World")
            syscall.Sleep(1e9)
        }
    }()
    syscall.Sleep(10e9)
}

関数を抜けた際に処理を実行するにはどうするか?

defer命令を使用します。 package main

func foo() {
    defer func() {
        println("bye")
    }()
    println("hi")
}

func main() {
    foo()
}

goroutineの同時実行数を変更するにはどうするか?

環境変数GOMAXPROCSの値を数値で設定するか、runtime.GOMAXPROCS()で設定します。

コンパイラやリンカが8g/6g/5g、8l/6l/5lという名前になっている理由は?

Plan9由来の名前とされています。開発メンバのRuss CoxはPlan9の開発者でもあります。
FAQ - The Go Programming Language

What kind of a name is 6g?

http://golang.org/doc/go_faq.html#What_kind_of_a_name_is_6g

Goのガベージコレクションの実装は一般的に何と呼ばれている類か?

現在はmark and sweepで実装されています。
FAQ - The Go Programming Language

Why do garbage collection?

http://golang.org/doc/go_faq.html#garbage_collection

レシーバがnilの場合にメソッドを呼び出すと何が起きるか?

落ち...ません。レシーバに対してメソッドを定義している訳ではありません。なのでプリミティブな型に対してレシーバを定義する事も出来ます。 package main

import "fmt"

type foo float64

func (f foo) bar() {
    fmt.Printf("called foo.bar(%f)\n", f)
}

func main() {
    f := foo(1.23)
    f.bar()
}

また属性を持たせたい場合はstructを使用します。 package main

type point struct {
    x int
    y int
}

func (p *point) setXY(x, y int) {
    p.x, p.y = x, y
}

func (p *point) getXY() (intint) {
    return p.x, p.y
}

func main() {
    p := point{}
    p.setXY(12)
    x, y := p.getXY()
    println(x, y)
}

さらに配列やmapに足してレシーバを定義する事も出来ます。なお、以下の様にpoint型のポインタppに対してnilを設定してもsetXYは呼び出せますが、そのレシーバ内でpを触ると例外が発生します。 package main

type point struct {
    x int
    y int
}

func (p *point) setXY(x, y int) {
    println("もうすぐ死ぬ")
    p.x, p.y = x, y
}

func (p *point) getXY() (intint) {
    println("もうすぐ死ぬ")
    return p.x, p.y
}

func main() {
    var p *point
    p = nil

    p.setXY(12// panic でも「もうすぐ死ぬ」は表示される
}
C++でいう、メソッド内でthisがNULL...みたいな物ですね。気持ち悪いですね!

可変個引数はどの様に定義するか?

...を使います。 package main

func foo(v ...string) {
    for _, s := range v {
        println(s)
    }
}

func main(){
    foo("お前は""もう""死んでいる")
}

関数内で定義されるローカル変数のアドレスを戻り値として外部から参照するとどうなるか?

落ち...ません。Goはローカルヒープの管理もされているので、まったく問題ありません。 package main

func foo() *int {
    i := 3
    return &i;
}

func main() {
    p := foo()
    println(*p)
}

interfaceとstructの違いは何か?

interfaceはその名の通りインタフェースを指し、structは構造体を指します。
ただしGoのinterfaceは他の言語のそれと同じ様に構造体・クラスのインタフェースを定義するだけの物ではありません。
GoはDuck Typingによる動的型付けで処理されinterfaceはその型拘束を提供します。構造体とinterfaceは継承関係(定義と実装の関係)でなくても構いません。 またプリミティブな型にも適用されます。 package main

type human interface {
    sing()
}

type people int

func (p people) sing() {
    println("Hi")
}

func main() {
    var i human
    i = people(69)
    i.sing() // Hi
    println(i.(people)) // 69
}
interface{} は空のインタフェースを示します。引数の型にinterface{}を使用すると、どんな型でも渡せる様になります。

panicを補足して強制終了させない為にはどうするか?

panicは強制終了させる為の命令ですが、recover命令を使用すれば例外として補足出来ます。 package main

func main() {
    defer func() {
        if err := recover(); err != nil {
            println(err.(string), "\nと思わせて死なない!")
        }
    }()

    panic("死ぬ!")
}


その他、Goの面白い特徴として、定義にutf-8が使えます。 package main

type おっぱい int

func (オッパイ おっぱい) 今何おっぱい() {
    println(オッパイ, "おっぱい")
}

func main() {
    var おっぱいぱい おっぱい
    おっぱいぱい++
    おっぱいぱい++
    おっぱいぱい++
    おっぱいぱい++
    おっぱいぱい++

    おっぱいぱい.今何おっぱい()
}

Goのtipsがもっと見たい人は、「おっぱいおっぱい」と入力して下さい。
Posted at by